﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 实体类
/// 所有怪物，NPC主角由该类派生
/// 实现生命值，受伤，死亡
/// </summary>
public abstract class Entity : MonoBehaviour,IVictim
{
    #region feild

    [Tooltip("生命值上限")]
    [SerializeField]
    protected int hpLimit=5;
    [Tooltip("当前生命值")]
    [SerializeField]
    protected int hp=4;

    [Tooltip("获取音乐脚本")]
    private ObtainMusic obtainMusic;
    public event Action<float> OnHpChange;//Hp变化事件
    public event Action<float> OnHpLimitChange;//血量上限变化
    public event Action<KOMusic> OnChangeSound;//音效改变事件

    public event Action OnDeath;
    //public event
    #endregion


    #region dir
    public static Vector3[] eEect = new Vector3[4] {new Vector3(0,-1,0),new Vector3(-1,0,0),
                    new Vector3(0,1,0),new Vector3(1,0,0)};//分别对应四个方向的向量

    #endregion


    #region propertise

    public int Hp
    {
        get
        {
            return hp;
        }
        set
        {
            if (value < 1)
            {
                hp = 0;
                if (OnDeath != null)
                {
                    OnDeath();//生命值归零死亡
                }
                Death();
            }
           else if (OnHpChange != null && value <= hpLimit) OnHpChange(value);
           // print(value);
            if (value > hpLimit)//生命值不能超出生命上限
            {
                hp = hpLimit;
            }
            else
            {
                if (OnChangeSound != null && value<hp) OnChangeSound(obtainMusic.musicGather[0]);
                else if(OnChangeSound!=null&&value>hp) OnChangeSound(obtainMusic.musicGather[2]);
                hp = value;
            }
            
        }
    }
    public int HpLimit
    {
        get
        {
            return hpLimit;
        }

        set
        {
            if (value <= 7&&value>=4)
            {
                if (value < 1)
                {
                    hpLimit = 6;
                    Debug.LogError(name + " hplimit can't <1");//生命值上限不能为负数或0
                }
                else
                {
                    if (hp == hpLimit && value < hpLimit)
                        Hp -= 1;
                    hpLimit = value;
                }
                if (OnHpLimitChange != null) OnHpLimitChange(value);
            }
        }
    }


    #endregion
    #region virtualMethod
    /// <summary>
    /// 受到伤害
    /// 根据伤害信息处理数据
    /// </summary>
    /// <param name="d">伤害信息</param>
    public virtual void GetDamage(Damage d)
    {
        Hp -= d.Hurt;
    }
    public virtual void Death()
    {
        GameObject.Destroy(gameObject);
    }


    
    protected virtual void Awake()
    {
        tag = "Entity";//entity都是actor，而且都是victim
        obtainMusic = GetComponent<ObtainMusic>();
    } 


    #endregion
}


#region Adds

/// <summary>
/// 伤害信息结构体
/// 包含 伤害值，伤害类型攻击者
/// </summary>
[System.Serializable]
public class Damage
{
    [SerializeField, Tooltip("伤害值")]
    int hurt;
    [SerializeField, Tooltip("攻击者")]
    Entity attacker;
    [SerializeField, Tooltip("攻击类型")]
    DamageType type;
    [SerializeField, Tooltip("受伤者")]
    private IVictim victim;

    public int Hurt
    {
        get
        {
            return hurt;
        }
        set
        {
            if (value < 0)
            {
                hurt = 0;
            }
            else hurt = value;
        }
    }

    public Entity Attacker
    {
        get
        {
            return attacker;
        }
    }

    public DamageType Type
    {
        get
        {
            return type;
        }
    }
    /// <summary>
    /// 受伤者确定时伤害事件就发生了
    /// </summary>
    public IVictim Victim
    {
        get
        {
            return victim;
        }

        set
        {
            if (value != null)
            {
                victim = value;
                victim.GetDamage(this);
            }
        }
    }

    public Damage(int hurt, Entity attacker, DamageType type)
    {
        this.hurt = hurt;
        this.attacker = attacker;
        this.type = type;
    }

    public Damage(Entity at, DamageType ty) : this(1, at, ty) { }//默认伤害值为1
    public Damage(int hurt, DamageType ty) : this(hurt, null, ty) { }//默认攻击者为null。攻击者为场景时即为null

}

/// <summary>
/// 伤害类型：物理，火焰，激光
/// </summary>
public enum DamageType
{
    PHYSIC, FIRE, XRAY
}

/// <summary>
/// 受伤者。会受到伤害的obj需要实现此接口
/// </summary>
public interface IVictim
{
    void GetDamage(Damage d);
}


/// <summary>
/// 方向
/// ahead是朝下方
/// 按照前左后又的方向，不要改动
/// </summary>
public enum Direction
{
    Ahead, Left, Back, Right
}

#endregion

